﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace IndustryWrapper
{
    /// <summary>
    /// 轴定义
    /// 所有的轴状态属性都在这里
    /// 对应的这个轴参数也在这个类里
    /// </summary>
    [Serializable]
    public class CAxisRef
    {
        public static int idCount = 0;
        //状态
        public bool servoOn = false;
        public short homed = 0;//0=刚初始化没做过动作 1 成功 -1失败 2=还在进行
        //状态
        public bool alarm = false, limitP = false, limitN = false;
        public bool followErr = false;
        public bool moving = false;
        public volatile bool isHoming = false;//如果在回零过程中 可能会进行回零检测
        public bool swHome = false, swLmtP = false, swLmtN = false;//回零开关 正限位开关 负限位开关.
        public bool inPos = false;//这个是立即指令,每次调用会读取目标位置  轴状态 来判断是否停止并且到位.
        public double cmdPos = 0.0f, relPos = 0.0f, cmdVel = 0.0f, relVel = 0.0f,followPos = 0;
        public double targetPos = 0.0;//目标位置,用来做到位判断
        public double sts_src = 0;
        //回零属于异步调用,有可能会产生一个线程,别的动作之前都需要先判断是否处于HOME中
        public Task homeTask = null;
        public volatile bool cancelHome = false;//取消操作
        public bool estopincludehome = false;//急停的时候停止回零
        //参数
        public CAxisSinglePrm prm = new CAxisSinglePrm();
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public CAxisRef()
        {
            prm.ID = -1;
        }
        public CAxisRef(int ID)
        {
            prm.ID = ID;
            if (!assignPrm())
            {
                CDebug.log.add("没有找到轴ID为:" + ID.ToString() + "的轴参数");
                return;
            }
        }
        private bool assignPrm()
        {
            List<CAxisSinglePrm> cfg = CGlbMc.axisPrm.data;
            for (int i = 0; i < cfg.Count; i++)
            {
                if (cfg[i].ID == prm.ID)
                {
                    prm = cfg[i];
                    cfg[i].AxisRefPointer = this;
                    return true;
                }
            }
            return false;
        }
    };
    /// <summary>
    /// IO的基类
    /// 所有的IO点都要继承至这里
    /// </summary>
    public class CIOBase
    {
        public CIoSinglePrm prm = new CIoSinglePrm();
        /// <summary>
        /// 构造的时候需要指定硬件ID号
        /// </summary>
        /// <param name="id"></param>
        public CIOBase(int id)
        {
            if (id == 0)
                return;
            if (!assignID(id))
            {
                CDebug.log.add("IO号为" + id.ToString() + "的IO点映射失败", ELogType.ERROR);
            }
        }
        private bool assignID(int id)
        {
            var p = CGlbMc.ioPrm.prmList;
            foreach (var item in p)
            {
                if (item.id == id)
                {
                    prm = item;
                    return true;
                }
            }
            return false;
        }
    }
    /// <summary>
    /// 模拟量输入点
    /// </summary>
    public class CIO_Ai:CIOBase
    {
        public CIO_Ai(int id) : base(id)
        {
        }
        /// <summary>
        /// 这个属性是让用户直接从刷新库中获取值
        /// 效率会低一点,但是通讯带宽占用会降低
        /// </summary>
        public float Value
        {
            get
            {
                if (prm.id == 0)
                    return 0;
                return CMotionManager.aiData[prm.dIndex];
            }
        }
    }
    /// <summary>
    /// 模拟量输出点
    /// </summary>
    public class CIO_Ao:CIOBase
    {
        public CIO_Ao(int id):base(id)
        {

        }
        /// <summary>
        /// 这个属性是让用户直接从刷新库中获取值
        /// 效率会低一点,但是通讯带宽占用会降低
        /// </summary>
        public float Value
        {
            get
            {
                if (prm.id == 0)
                    return 0;
                return CMotionManager.aoDataNow[prm.dIndex];
            }
            set
            {
                if (prm.id != 0)
                    CMotionManager.aoDataSet[prm.dIndex] = value;
            }
        }
    }

    /// <summary>
    /// 输入点定义
    /// 所有程序中都应该用这个来定义
    /// </summary>
    public class CIO_Di:CIOBase
    {
        public long counter = 0;//IO有计数器
        public CIO_Di(int id):base(id)
        {

        }
        public long Count
        {
            get
            {
                return counter;
            }
        }
        /// <summary>
        /// 这个属性是让用户直接从刷新库中获取值
        /// 效率会低一点,但是通讯带宽占用会降低
        /// </summary>
        public bool Value
        {
            get
            {
                if (prm.id == 0)
                    return false;
                return CMotionManager.diData[prm.dIndex];
            }
        }
    }
    /// <summary>
    /// io里面的编码器输入口
    /// </summary>
    public class CIO_Enc:CIOBase
    {
        public CIO_Enc(int id):base(id)
        {

        }
        /// <summary>
        /// 这个属性是让用户直接从刷新库中获取值
        /// 效率会低一点,但是通讯带宽占用会降低
        /// </summary>
        public long Value
        {
            get
            {
                if (prm.id == 0)
                    return 0;
                return CMotionManager.encData[prm.dIndex];
            }
        }
    }
    /// <summary>
    /// 输出点定义
    /// 所有程序中的输出 都应该以这个点来定义
    /// </summary>
    public class CIO_Do:CIOBase
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="id">唯一ID  0表示没有映射</param>
        public CIO_Do(int id):base(id)
        {

        }
        /// <summary>
        /// 需要临时构建一个DO来输出的时候,就用这个构造方式
        /// </summary>
        /// <param name="prm"></param>
        public CIO_Do(CIoSinglePrm prm):base(0)
        {
            this.prm = prm;
        }
        /// <summary>
        /// 这个属性是让用户直接从刷新库中获取值
        /// 效率会低一点,但是通讯带宽占用会降低
        /// </summary>
        public bool Value
        {
            get
            {
                if (prm.id == 0)
                    return false;
                return CMotionManager.doData[prm.dIndex];
            }
            set
            {
                if (prm.id != 0)
                    CMotionManager.doData[prm.dIndex] = value;
            }
        }
    }
    /// <summary>
    /// 模块类型
    /// </summary>
    public enum CIoModelType
    {
        I16O16 = 1,
        I16 = 2,
        O16 = 3,
        I32 = 4,
        O32 = 5,
        AD8DA4 = 6,
        AD6DA4 = 7,
        ENC2 = 8,
        ENC4 = 9
    }
    /// <summary>
    /// TODO:很难统一各种编码器 模拟量 所有的输入输出 需要更优雅的去实现
    /// IO模块 内部可能包含了很多IO
    /// 如何划分模块没有约定.
    /// 控制卡本身算一个模块
    /// 外接模块又算别的模块
    /// 每个模块还需要考虑整体数据刷新的调用
    /// 通过这个模块来访问的话,是内部刷新的一个值,如果需要立刻当前值,就用接口的来访问.
    /// </summary>
    public class CIoModel
    {
        public string name = "";//模块的名称
        //模块的配置--数量和模块选项一致
        public List<CIoSinglePrm> iList = new List<CIoSinglePrm>();
        public List<CIoSinglePrm> oList = new List<CIoSinglePrm>();
        public List<CIoSinglePrm> aiList = new List<CIoSinglePrm>();
        public List<CIoSinglePrm> aoList = new List<CIoSinglePrm>();
        public List<CIoSinglePrm> encList = new List<CIoSinglePrm>();
        public List<CIoSinglePrm> cmpList = new List<CIoSinglePrm>();
        public CIoModelPrm prm = new CIoModelPrm();
        //计数器
        public static short CounterMd = 0;//模块的ID
        public static short CounterDi = 0;
        public static short CounterDo = 0;
        public static short CounterAi = 0;
        public static short CounterAo = 0;
        public static short CounterEnc = 0;
        public static short CounterCmpout = 0;
        public static void clear()
        {
            CounterDi = 0;
            CounterDo = 0;
            CounterAi = 0;
            CounterAo = 0;
            CounterEnc = 0;
            CounterCmpout = 0;
        }
        public CIoModel()
        {
            prm.diDataStart = (short)(CounterDi+1);
            prm.doDataStart = (short)(CounterDo +1);
            prm.aiDataStart = (short)(CounterAi +1);
            prm.aoDataStart = (short)(CounterAo +1);
            prm.encDataStart = (short)(CounterEnc +1);
            prm.cmpDataStart = (short)(CounterCmpout +1);
        }
        #region 属性
        public short DiCount
        {
            get
            {
                return (short)iList.Count;
            }
        }
        public short DoCount
        {
            get
            {
                return (short)oList.Count;
            }
        }
        public short AiCount
        {
            get
            {
                return (short)aiList.Count;
            }
        }
        public short AoCount
        {
            get
            {
                return (short)aoList.Count;
            }
        }
        public short EncCount
        {
            get
            {
                return (short)encList.Count;
            }
        }
        public short CmpCount
        {
            get
            {
                return (short)cmpList.Count;
            }
        }
        #endregion
        public void addIO(CIoSinglePrm p)
        {
            switch (p.ioType)
            {
                case ESingleIoType.Input:
                    iList.Add(p);
                    break;
                case ESingleIoType.Output:
                    oList.Add(p);
                    break;
                case ESingleIoType.AInput:
                    aiList.Add(p);
                    break;
                case ESingleIoType.AOutput:
                    aoList.Add(p);
                    break;
                case ESingleIoType.EncoderInut:
                    encList.Add(p);
                    break;
                case ESingleIoType.CompareOut:
                    cmpList.Add(p);
                    break;
            }

        }
        
    }
    /// <summary>
    /// 一个模块的当前运行模式
    /// </summary>
    public enum ERunMode
    {
        MANUAL = 0,     //手动模式
        AUTO = 1,       //自动模式
        PAUSE = 2,      //暂停模式
        HOME = 3,       //回零模式
        OHTER = 4       //其他模式
    }
    /// <summary>
    /// 需要代理声明的全部在这里
    /// </summary>
    public class CPublicDelegate
    {
        public delegate void fun_one_prm(int p);
        public delegate void fun_int_bool(int p, bool b);
        public delegate void fun_none_prm();
    }
    /// <summary>
    /// 机器的基本类
    /// 所有的可运行组件都要继承自这里
    /// 不同的卡 要在这里添加
    /// </summary>
    public class CMachBase
    {
        public CPublicDelegate.fun_none_prm closefun = null;
        public string machname = "默认模组名称";
        public Thread runThread = null;//内部使用的线程
        public Thread homeThread = null;//回零用的传感器
        public ERunMode runModel = ERunMode.MANUAL;//当前运行模式
        public bool threadSelf = false;//拥有自由线程  一般情况下用大线程来做 自身模块不具备线程
        public bool initSuccess = false;
        public bool threadCanRun = true;//线程启用
        public bool startNeedStatusOk = false;//必须状态OK才能启动,有的组件临时出现异常 也是可以运行的
        public volatile int stepAuto = 0, stepPause = 0, stepHome = 0;//自动执行得流程  暂停的时候保存的流程号
        //模块的整体状态回零OK 有报警 有限位触发 在运动
        public volatile bool homeok = false, alm = true, lmt = true, move = false, allok = false, servoOn = false;
        public double beilv = 1.0f;//改模块的运动倍率
        public double jogBeilv = 1.0f;//单轴电动的时候的倍率
        //轴列表,会把子类的都列举出来
        public List<CAxisRef> axisList = new List<CAxisRef>();
        public List<CIO_Di> inList = new List<CIO_Di>();
        public List<CIO_Do> outList = new List<CIO_Do>();
        //接口-一些最基本的接口
        public IMotionPartI p1 = null;
        public IIoPart pio = null;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="haveselthread">是否拥有自有线程</param>
        public CMachBase(string name,bool haveselthread) 
        {
            machname = name;
            threadSelf = haveselthread;
            FreshAxisAndIo();
        }
        /// <summary>
        /// 在子类中调用
        /// 搜索出所有
        /// </summary>
        public void FreshAxisAndIo()
        {
            foreach (var item in AllAxis)
            {
                axisList.Add(item);
            }
            foreach (var item in AllInput)
            {
                inList.Add(item);
            }
            foreach (var item in AllOutput)
            {
                outList.Add(item);
            }
        }
        /// <summary>
        /// 反射,获取所有的轴
        /// </summary>
        /// <returns></returns>
        public List<CAxisRef> AllAxis
        {
            get
            {
                List<CAxisRef> axisList = new List<CAxisRef>();
                Type t = this.GetType();
                MemberInfo[] minfos = t.GetMembers();
                foreach (MemberInfo minfo in minfos)
                {
                    FieldInfo fi = this.GetType().GetField(minfo.Name);
                    if (fi != null && fi.FieldType.Name == "CAxisRef")//获取公有变量
                    {
                        axisList.Add((CAxisRef)fi.GetValue(this));
                    }
                }
                return axisList;
            }
        }
        /// <summary>
        /// 获取所有的输入引用
        /// </summary>
        public List<CIO_Di> AllInput
        {
            get
            {
                List<CIO_Di> inputList = new List<CIO_Di>();
                Type t = this.GetType();
                MemberInfo[] minfos = t.GetMembers();
                foreach (MemberInfo minfo in minfos)
                {
                    FieldInfo fi = this.GetType().GetField(minfo.Name);
                    if (fi != null && fi.FieldType.Name == "CIO_Di")//获取公有变量
                    {
                        inputList.Add((CIO_Di)fi.GetValue(this));
                    }
                }
                return inputList;
            }
        }
        /// <summary>
        /// 获取所有的输出引用
        /// </summary>
        public List<CIO_Do> AllOutput
        {
            get
            {
                List<CIO_Do> outputList = new List<CIO_Do>();
                Type t = this.GetType();
                MemberInfo[] minfos = t.GetMembers();
                foreach (MemberInfo minfo in minfos)
                {
                    FieldInfo fi = this.GetType().GetField(minfo.Name);
                    if (fi != null && fi.FieldType.Name == "CIO_Do")//获取公有变量
                    {
                        outputList.Add((CIO_Do)fi.GetValue(this));
                    }
                }
                return outputList;
            }
        }
        //主要的成员列表
        /// <summary>
        /// 模块启动,初始化完成后开始调用
        /// 会启动现成,刷新线程
        /// </summary>
        public virtual void Module_Start()
        {
               
        }
        /// <summary>
        /// 模块的关闭
        /// 停止所有动作和刷新
        /// 内部必须调用Auto_Stop来停止
        /// </summary>
        public virtual void Module_Stop()
        {

        }
        public virtual void Fresh()
        {

        }
        /// <summary>
        /// 自动启动
        /// </summary>
        /// <returns></returns>
        public virtual bool Auto_Start()
        {
            return true;
        }
        /// <summary>
        /// 自动模式下的停
        /// </summary>
        /// <returns></returns>
        public virtual bool Auto_Stop()
        {
            return true;
        }

        /// <summary>
        /// 只有处于手动模式 才能复位某些功能
        /// </summary>
        /// <returns></returns>
        public virtual bool Auto_Reset()
        {
            foreach (var item in axisList)
            {
                p1.MC_Reset(item);
            }
            return true;
        }
        /// <summary>
        /// 获取运动模式
        /// </summary>
        /// <returns></returns>
        public virtual void RunModel(int modelIndex, ref ERunMode modelNow)
        {
            modelNow = runModel;
        }
        public virtual bool Auto_Pause()
        {
            return true;
        }

        /// <summary>
        /// 托管线程运行的时候用的函数
        /// 内部不允许有while
        /// 自己没有执行时序和延迟等
        /// </summary>
        public virtual void RunFun_Delegate()
        {

        }
        /// <summary>
        /// 自有线程运行时函数写这边
        /// 所有刷新和流程判断都在这边
        /// 自己拥有一个while循环和sleep交出管理权
        /// </summary>
        public virtual void RunFun_Self()
        {

        }
        /// <summary>
        /// 预判当前状态是否正常 判断是否能够启动
        /// 注意:根据mustStsOk=true才需要检测,否则不检测这个模块的状态.
        /// </summary>
        /// <returns></returns>
        public virtual bool preCheckStatus()
        {
            return true;
        }
        /// <summary>
        /// 整个模块回零函数,这属于基类的回零,默认情况下用这个就足够了
        /// 会在多线程中执行
        /// </summary>
        private void HomeFun()
        {
            if (p1 == null)
                return;
            runModel = ERunMode.HOME;
            List<CAxisRef> tmpAxisList = new List<CAxisRef>();
            for (int i = 0; i < 10; i++)//总共10个等级
            {
                //搜索出所有这个顺序的轴
                tmpAxisList.Clear();
                foreach (var item in AllAxis)
                {
                    if (item.prm.homeSequence == i)
                    {
                        tmpAxisList.Add(item);
                    }
                }
                //找到了这个轴
                int homeStatus = 0;//-1 失败  1 进行中  2 成功
                if (tmpAxisList.Count > 0)
                {
                    //启动
                    foreach (var item in tmpAxisList)
                    {
                        CAxisRef axis = item;
                        if (p1.MC_Home(ref axis) != 0)
                        {
                            //任意一个出现HOME错误 就停止  然后返回
                            foreach (var stopAxis in AllAxis)
                            {
                                p1.MC_EStop(stopAxis);
                            }
                            if (closefun!= null)
                                closefun();
                            runModel = ERunMode.MANUAL;
                            return;
                        }
                    }
                    //判断状态
                    homeStatus = 1;
                    while (homeStatus > 0)
                    {
                        homeStatus = 2;//假设成功
                        foreach (var item in tmpAxisList)
                        {
                            CAxisRef axis = item;
                            p1.MC_HomeStatus(ref axis);
                            if (axis.isHoming)
                            {
                                homeStatus = 1;
                            }
                            else
                            {
                                if (axis.homed == -1)//Home失败
                                {
                                    //任意一个出现HOME错误 就停止  然后返回
                                    foreach (var stopAxis in tmpAxisList)
                                    {
                                        p1.MC_EStop(stopAxis);
                                    }
                                    homeStatus = -1;
                                    break;
                                }
                            }
                        }
                        if (homeStatus == 2)//这一组完成回零
                        {
                            break;
                        }
                        Thread.Sleep(5);
                    }
                }
                if (homeStatus < 0)
                {
                    runModel = ERunMode.MANUAL;
                    break;
                }
            }
            if (closefun != null)
                closefun();
            runModel = ERunMode.MANUAL;
        }
        /// <summary>
        /// 回零流程
        /// 如果没有特殊流程,就调用这个来实现就完事儿
        /// </summary>
        /// <returns></returns>
        public virtual bool Auto_Home()
        {
            if (homeThread != null && homeThread.IsAlive)
            {
                homeThread.Abort();
                Thread.Sleep(5);
            }
            homeThread = null;
            homeThread = new Thread(HomeFun);
            homeThread.IsBackground = true;
            homeThread.Start();
            return true;
        }
    }
    /// <summary>
    /// 机器类,所有的并行组件都在这边
    /// 内部会构建一个线程
    /// 线程负责管理所有的子类的流程
    /// </summary>
    public class CMachManager
    {
        public CMessageManager msg = new CMessageManager();
        public bool initSuccess = false;
        public ERunMode runModel = ERunMode.MANUAL;//运行模式
        public volatile bool homeok = false, alm = true, lmt = true, move = false, allok = false, servoOn = false;
        //所有的机器组件都在这个列表中
        public List<CMachBase> machlist = new List<CMachBase>();
        //输入
        CIO_Di iStart = new CIO_Di(0);
        CIO_Di iPause = new CIO_Di(0);
        CIO_Di iStop = new CIO_Di(0);
        CIO_Di iHome = new CIO_Di(0);
        CIO_Di iReset = new CIO_Di(0);
        //输出
        CIO_Do oGreen = new CIO_Do(0);
        CIO_Do oYellow = new CIO_Do(0);
        CIO_Do oRed = new CIO_Do(0);
        //局部变量
        IIoPart p1 = null;//这个用来监控启停信号和三色灯信号之类的
        private bool canrun = false;
        private bool haveOne = false;//至少有一个模块需要运行
        private Thread td = null;
        public CMachManager()
        {
            p1 = CGlbMc.mc.iio;
        }
        /// <summary>
        /// 添加一个机器模型
        /// </summary>
        /// <param name="inMach"></param>
        public void addMach(CMachBase inMach)
        {
            if (inMach != null)
            {
                machlist.Add(inMach);
                msg.addMessage("添加模组:" + inMach.machname);
            }
        }
        public bool StartGantry()
        {
            //GTN.mc.GTN_SetAxisConjugateVibrationSuppresionPrm();
            return true;
        }
        /// <summary>
        /// 通过ID获取模块名称  
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public CMachBase getMach(string id)
        {
            if (id == "")
                return null;
            foreach (var item in machlist)
            {
                if (item.machname == id)
                {
                    return item;
                }
            }
            return null;
        }
        /// <summary>
        /// 检测是否状态正常
        /// </summary>
        /// <returns></returns>
        public bool preCheckStatus()
        {
            bool statusAll = true;
            foreach (CMachBase item in machlist)
            {
                if (item.startNeedStatusOk && !item.preCheckStatus()) 
                    statusAll = false;
            }
            return statusAll;
        }
        /// <summary>
        /// 刷新所有设备的状态
        /// </summary>
        private void Fresh()
        {
            foreach (CMachBase item in machlist)
            {
                if(!item.threadSelf)
                    item.Fresh();
            }
        }
        /// <summary>
        /// 设备整体回零
        /// </summary>
        /// <returns></returns>
        public bool Auto_Home()
        {
            bool statusAll = true;
            foreach (CMachBase item in machlist)
            {
                if (!item.Auto_Home())
                {
                    statusAll = false;
                    break;
                }
            }
            if (!statusAll) Auto_Stop();
            runModel = ERunMode.HOME;
            return statusAll;
        }
        /// <summary>
        /// 模块启动
        /// 整个程序只会启动一次
        /// 取消每个模块本身的初始化动作
        /// </summary>
        public void Module_Start()
        {
            //模组线程开启
            short haveOne =0;
            foreach (var item in machlist)
            {
                if(item.threadSelf)
                {
                    item.Module_Start();
                }
                else
                {
                    haveOne++;
                }
            }
            if (haveOne >0)//表示还有一部分是需要托管运行的
            {
                //自有线程开启
                td = new Thread(Run);
                td.Priority = ThreadPriority.AboveNormal;
                td.IsBackground = true;
                td.Start();
            }
        }
        /// <summary>
        /// 模块内部停止
        /// </summary>
        public void Module_Stop()
        {
            short haveOne = 0;
            foreach (var item in machlist)
            {
                if (item.threadSelf)
                {
                    item.Module_Stop();
                }
                else
                {
                    haveOne++;
                }
            }
            if (haveOne > 0)
            {
                if (td != null && td.IsAlive)
                {
                    canrun = false;
                    while (td.IsAlive)
                    {
                        Thread.Sleep(1);
                    }
                    td = null;
                }
            }
            else
            {
                td = null;
            }
        }
        /// <summary>
        /// 设备整体暂停
        /// </summary>
        /// <returns></returns>
        public bool Auto_Pause()
        {
            bool paused = true;
            foreach (CMachBase item in machlist)
            {
                if (!item.Auto_Pause()) paused = false;
            }
            if (paused)
            {
                runModel = ERunMode.PAUSE;
            }
            return paused;
        }

        public bool Auto_Reset()
        {
            foreach (CMachBase item in machlist)
            {
                item.Auto_Reset();
            }
            return true;
        }
        /// <summary>
        /// 整个设备的主任务
        /// </summary>
        public void Run()
        {
            canrun = true;
            while (canrun)
            {
                Fresh();
                foreach (var item in machlist)
                {
                    if (!item.threadSelf)
                    {
                        item.RunFun_Delegate();
                        haveOne = true;
                    }
                }
                if (!haveOne)//没有一个模块需要运行,就跳出去
                    break;
                Thread.Sleep(1);
            }
        }
        public bool Auto_Start()
        {
            //先检测所有组件是否都已经准备就绪
            if (!preCheckStatus())
                return false;
            //能到这里说明所有组件准备好 可以启动
            foreach (CMachBase item in machlist)
            {
                item.Auto_Start();
            }
            runModel = ERunMode.AUTO;
            return true;
        }
        /// <summary>
        /// 停止整个系统
        /// </summary>
        /// <returns></returns>
        public bool Auto_Stop()
        {
            short haveOne = 0;
            foreach (CMachBase item in machlist)
            {
                item.Auto_Stop();
            }
            runModel = ERunMode.MANUAL;
            return true;
        }
        /// <summary>
        /// 返回某个组件的运行模式
        /// </summary>
        /// <param name="modelIndex"></param>
        /// <param name="md"></param>
        public void RunModel(int modelIndex, ref ERunMode md)
        {
            if (modelIndex >= 0 && modelIndex < machlist.Count)
            {
                md = machlist[modelIndex].runModel;
            }
        }
    }

    /// <summary>
    /// 运动控制器管理类
    /// 负责通过配置文件生成不同的控制器实际接口
    /// 最后将这些实际接口传递到不同的模组之中.
    /// </summary>
    public class CMotionManager
    {
        public int initOk = 0;//控制管理器是否成功 0=成功
        //封装的几个运控组件 需要传递到不同的组件之中
        public IIoPart iio = null;
        public IMotionPartI ip1 = null;
        public IMotionPartII ip2 = null;
        public IMotionPartSpecial ips = null;
        public IInitModel iinit = null;
        //私有数据
        private Thread freshThread = null;//状态刷新线程
        private int freshTime = 5;//控制器的数据刷新时间-MS
        private bool canFresh = false;//同意刷新
        //硬件参数组态文档
        private CMotionHardConfige hardPrm = null;
        #region 构想中-数据保存区域-所有外部的输入输出值都会映射到这里
        //轴数据
        private const int maxAxis = 64;
        public static CAxisRef[] axisData = new CAxisRef[maxAxis];
        //注意0这个位置是没有指定的时候用的
        private const int maxDi = 512;
        private const int maxDo = 512;
        private const int maxAi = 32;
        private const int maxAo = 32;
        private const int maxEnc = 32;
        public static bool[] diData = new bool[maxDi];         //输入点原始数据
        public static bool[] doDataSet = new bool[maxDo];     //输出点设置数据
        public static bool[] doData = new bool[maxDo];     //输出点当前值
        public static float[] aiData = new float[maxAi];        //已经转换成电压或者电流的值
        public static float[] aoDataSet = new float[maxAo];
        public static float[] aoDataNow = new float[maxAo];     
        public static long[] encData = new long[maxEnc];
        #endregion
        static CMotionManager()
        {
            for (int i = 0; i < maxAxis; i++)
            {
                axisData[i] = new CAxisRef();
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="hard">硬件配置文件,通过这个文件来初始化整个控制器</param>
        public CMotionManager(CMotionHardConfige hard)
        {
            if (hard != null)
            {
                hardPrm = hard;
                canFresh = hard.freshSelf;
                freshTime = hard.freshTime;
            }
            else
            {
                initOk += 1;
                CDebug.log.add("初始化硬件参数文件错误!", ELogType.ERROR);
                return;
            }
            if (!Init())
            {
                initOk += 2;
                CDebug.log.add("控制器初始化失败!", ELogType.ERROR);
                return;
            }
            if (!setPrm())
            {
                initOk += 4;
                CDebug.log.add("轴初始化失败!", ELogType.ERROR);
                return;
            }
        }
        /// <summary>
        /// 设置所有的轴相关参数
        /// </summary>
        /// <returns></returns>
        private bool setPrm()
        {
            List<CAxisSinglePrm> cfg = CGlbMc.axisPrm.data;
            for (int i = 0; i < cfg.Count; i++)
            {
                if (ip1.MC_SetAxisParameter(cfg[i]) != 0)
                {
                    CDebug.log.add("初始化设置所有轴参数的时候，轴" + i.ToString() + "出错!", ELogType.ERROR);
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 初始化控制器
        /// 会根据不同的配置文件来创建不同的物理卡
        /// 并把卡的接口赋值到本类中的接口,方便后续使用。
        /// </summary>
        /// <returns></returns>
        private bool Init()
        {
            if (hardPrm == null)
                return false;
            //初始化控制器
            switch (hardPrm.cardType)
            {
                case ECardType.GTS:
                    CMotion_GTS gts = new CMotion_GTS((CCfgGts)hardPrm.cfg);
                    if ((gts is IInitModel) && (gts as IInitModel).Init())
                    {
                        iio = gts as IIoPart;
                        ip1 = gts as IMotionPartI;
                        ip2 = gts as IMotionPartII;
                        ips = gts as IMotionPartSpecial;
                        iinit = gts;
                    }
                    else//错误的 就创建一个模拟的。
                    {
                        CMotion_Simulate sm1 = new CMotion_Simulate();
                        iio = sm1 as IIoPart;
                        ip1 = sm1 as IMotionPartI;
                        ip2 = sm1 as IMotionPartII;
                        ips = sm1 as IMotionPartSpecial;
                        iinit = sm1;
                        CDebug.log.add("gts卡初始化失败!", ELogType.ERROR);
                        return false;
                    }
                    break;
                case ECardType.GSN:
                    CMotionCard_GSN gsn = new CMotionCard_GSN((CCfgGsn)hardPrm.cfg);
                    if ((gsn is IInitModel) && (gsn as IInitModel).Init())
                    {
                        iio = gsn as IIoPart;
                        ip1 = gsn as IMotionPartI;
                        ip2 = gsn as IMotionPartII;
                        ips = gsn as IMotionPartSpecial;
                        iinit = gsn;
                    }
                    else//错误的 就创建一个模拟的。
                    {
                        CMotion_Simulate sm2 = new CMotion_Simulate();
                        iio = sm2 as IIoPart;
                        ip1 = sm2 as IMotionPartI;
                        ip2 = sm2 as IMotionPartII;
                        ips = sm2 as IMotionPartSpecial;
                        iinit = sm2;
                        CDebug.log.add("gsn卡初始化失败!", ELogType.ERROR);
                        return false;
                    }
                    break;
                case ECardType.GEN:
                    CMotionCard_GEN gen = new CMotionCard_GEN((CCfgGen)hardPrm.cfg);
                    if ((gen is IInitModel) && (gen as IInitModel).Init())
                    {
                        iio = gen as IIoPart;
                        ip1 = gen as IMotionPartI;
                        ip2 = gen as IMotionPartII;
                        ips = gen as IMotionPartSpecial;
                        iinit = gen;
                    }
                    else
                    {
                        CMotion_Simulate sm3 = new CMotion_Simulate();
                        iio = sm3 as IIoPart;
                        ip1 = sm3 as IMotionPartI;
                        ip2 = sm3 as IMotionPartII;
                        ips = sm3 as IMotionPartSpecial;
                        iinit = sm3;
                        CDebug.log.add("gen卡初始化失败!", ELogType.ERROR);
                        return false;
                    }
                    break;
                case ECardType.GAOCHUAN:
                    break;
                case ECardType.LEISAI:
                    break;
                case ECardType.LINGHUA:
                    break;
                case ECardType.GVN:
                    CMotionCard_GVN gvn = new CMotionCard_GVN((CCfgGvn)hardPrm.cfg);
                    if ((gvn is IInitModel) && (gvn as IInitModel).Init())
                    {
                        iio = gvn as IIoPart;
                        ip1 = gvn as IMotionPartI;
                        ip2 = gvn as IMotionPartII;
                        ips = gvn as IMotionPartSpecial;
                        iinit = gvn;
                    }
                    else
                    {
                        CMotion_Simulate sm3 = new CMotion_Simulate();
                        iio = sm3 as IIoPart;
                        ip1 = sm3 as IMotionPartI;
                        ip2 = sm3 as IMotionPartII;
                        ips = sm3 as IMotionPartSpecial;
                        iinit = sm3;
                        CDebug.log.add("gvn卡初始化失败!", ELogType.ERROR);
                        return false;
                    }
                    break;
            }
            //成功后开始刷新
            if (canFresh)
            {
                freshThread = new Thread(fresh);
                freshThread.IsBackground = true;
                freshThread.Start();
            }
            return true;
        }
        /// <summary>
        /// 关闭控制器
        /// 注意关闭之前需要关闭所有的模组
        /// 一般放在最后
        /// </summary>
        /// <returns></returns>
        public bool UnInit()
        {
            if (freshThread != null && freshThread.IsAlive)
            {
                canFresh = false;
                while (freshThread.IsAlive)
                {
                    Thread.Sleep(1);
                }
                freshThread = null;
            }
            if (iinit != null)
                iinit.UnInit();
            return true;
        }
        /// <summary>
        /// 刷新所有的数据
        /// </summary>
        private void fresh()
        {
            canFresh = true;
            //设置刷新时间限制
            if (freshTime < 1)
                freshTime = 1;
            if(freshTime > 10)
                freshTime = 10;
            //刷新流程
            while (canFresh)
            {
                //刷新IO
                if (iio != null)
                {
                    foreach (var item in CGlbMc.ioPrm.data)
                    {
                        iio.MC_GetModel(item);
                    }
                }
                //刷新轴
                if (ip1 == null)
                {
                    foreach (var item in CGlbMc.axisPrm.model)
                    {
                        ip1.MC_AxisRef(item);
                    }
                }
                Thread.Sleep(freshTime);
            }
        }
    }
    /// <summary>
    /// 单个点的类型
    /// </summary>
    public enum ESingleIoType
    {
        Input = 1,
        Output = 2,
        AInput = 3,
        AOutput = 4,
        EncoderInut = 5,
        CompareOut = 6
    }
    /// <summary>
    /// 绝对值编码器的类型
    /// 通讯类型
    /// </summary>
    public enum EAbsEncType
    {
        COM232 = 0,
        COM485 = 1,
        TCP = 2
    }
    /// <summary>
    /// 控制卡类型
    /// </summary>
    public enum ECardType
    {
        GTS = 0,
        GSN = 1,
        GEN = 2,
        GAOCHUAN = 3,
        LEISAI = 4,
        LINGHUA = 5,
        GUC = 6,
        GNS = 7,
        GVN=8
    }
}
